BITS 16

%include "macrosmodoreal.mac"
%include "macrosmodoprotegido.mac"

%define KORG 0x1200

;SELECTORES GDT
%define VIDEO 10000b       ; pos=1
%define DATOS 100000b      ; pos=2
%define CODIGO 110000b     ; pos=3


global start
extern tsss
extern gdt, GDT_DESC
extern IDT_DESC
extern inicializar_idt
extern inicializar_dir_kernel
extern inicializar_mmu
extern inicializar_tss_desc
extern inicializar_scheduler

extern resetear_pic
extern habilitar_pic
extern deshabilitar_pic


;=====================
; FUNCIONES DE TESTEO
;=====================
extern make_calls
extern generar_db
extern generar_gp
extern recorrer_dir
extern inicializar_dir_usuario
extern mapear_pagina
extern unmapear_pagina

;Aca arranca todo, en el primer byte.
start:
		cli ;no me interrumpan por ahora
		;xchg bx, bx
		jmp bienvenida

;aca ponemos todos los mensajes
iniciando: db 'Iniciando el kernel'
iniciando_len equ $ - iniciando

numeros: db '0123456789'
numeros_len equ $ - numeros

global isrnombregrupo, isrnombregrupo_len
isrnombregrupo: db 'Angiulino "El Chino" Cubrepileta'
isrnombregrupo_len: equ $-isrnombregrupo

bienvenida:

		IMPRIMIR_MODO_REAL iniciando, iniciando_len, 0x07, 0, 0
		
    ;Habilitar A20
        call deshabilitar_A20
        call checkear_A20
        call habilitar_A20
        call checkear_A20
        
    ;Dehsabilitar las interrupciones
		cli
        
    ;Pasar a modo protegido
        lgdt [GDT_DESC]
        
        mov eax, cr0
        or eax, 1
        mov cr0, eax

        jmp CODIGO:modo_protegido ; saltamos a modo protegido

BITS 32
modo_protegido:

    ; SETEAMOS SEGMENTOS RESTANTES
	    xor eax, eax
	    mov ax, DATOS   
	    mov ds, ax		    ; data segment
	    mov fs, ax		    ; 
	    mov gs, ax          ;
        mov ss, ax          ;
	    mov ax, VIDEO   
        mov es, ax          ;es selector de segmento de video
        
    ; Seteamos los registros de la pila.
		mov ebp, 0x17000
		mov esp, ebp
        
    ; LIMPIAR PANTALLA
        call limpiar_pantalla

    ; IMPRIMIR LINEAS BLANCO
        call imprimir_lineas
       
    ; IMPRIME LISTA DE NUMEROS
        IMPRIMIR_TEXTO numeros, numeros_len, 0x70, 0, 70
;======================
; EJERCICIO 2
;======================
        call deshabilitar_pic   
        call resetear_pic
        call habilitar_pic
        
		;Inicializar la IDT
        call	inicializar_idt
		lidt	[IDT_DESC]

    ;~~~~~~~~~~~~~~
    ; TESTING EJ 2
    ;~~~~~~~~~~~~~~        
        ; GENERA EXCEPCIONES
        ;~ call generar_db
        ;~ call generar_gp
        
        ; GENERA un DB con 5 calls apiladas
        ; 2 calls ya vienen en generar y make_calls
        ;~ push dword 3
        ;~ push generar_db
        ;~ call make_calls 
        ;~ add esp, 4

        ;~ sti                          ; HABILITAR LAS INTERRUPCIONES ANTES DE  REPROGRAMAR LA PIC HACE QUE 
                                        ; EL TIMER TICK DISPARE LA RUTINA DE ATENCION DE LA DOBLE FALTA: TIPO 8
		
;======================
; EJERCICIO 3 y 4
;======================
		;Habilitar paginacion
        call inicializar_dir_kernel    ; cr3 <- PD (4Mb identity map)

        mov eax, cr0
        or eax, 0x80000000
        mov cr0, eax                   ; paginacion activada

        ;intercambio mapa de memoria
        call inicializar_mmu           ; cr3 <- PD (2Mb identity map)


        ;Imprime nombre de grupo
        IMPRIMIR_TEXTO isrnombregrupo, isrnombregrupo_len, 0x70, 0, 0

    ;~~~~~~~~~~~~~~~~~~
    ; TESTING EJ 3 y 4
    ;~~~~~~~~~~~~~~~~~~        
        ; RECORRE INDENTITY MAP DEL KERNEL
        ;~ push dword 0x400000   ; 4Mb  -- si accedo a la siguiente posicion me da page fault
        ;~ push dword 0x0        ; INCIO
        ;~ call recorrer_dir
        ;~ add esp, 8
        ;~ 
        ;~ xchg bx, bx
        ;~ 
        ; RECORRE INDENTITY MAP DEL USUARIO
        ;~ call inicializar_dir_usuario
        ;~ mov cr3, eax                ; carga el PD 
        ;~ push dword 0x200000   ; 2Mb -- si accedo a la siguiente posicion me da page fault
        ;~ push dword 0x0        ; INCIO
        ;~ call recorrer_dir
        ;~ add esp, 8
        
        ; PRUEBA MAPEAR Y UNMAPEAR
        ;~ push dword 0xB8000
        ;~ mov eax, cr3
        ;~ push eax
        ;~ push dword 0xFFFFF008            ;Mapea la ultima pagina de los 4Gb a la primera del video
        ;~ call mapear_pagina
        ;~ add esp, 12
        ;~ 
        ;~ xchg bx, bx
        ;~ mov word [0xFFFFF008], 0x0730    ;Escribe 0 en la primera posicion de la pantalla 
        ;~ 
        ;~ mov eax, cr3
        ;~ push eax
        ;~ push dword 0xFFFFF008            ;Desmapea el ultimo mapeo 
        ;~ call unmapear_pagina
        ;~ add esp, 8

;======================
; EJERCICIO 5
;======================
		;Inicializar el scheduler de tareas
        call inicializar_tss_desc
        call inicializar_scheduler
        
        ;~ xchg bx,bx
        mov ax, 0x18
        ltr ax
        
        ;Salta a la tarea idle
        ;~ xchg bx,bx
        jmp 0x28:0
        
        ;~ jmp tarea_idle

		;Construir tarea idle
		
		;Construir primer worm

		;Saltar a la primer tarea
        
        ;Imprime nombre de grupo
        IMPRIMIR_TEXTO isrnombregrupo, isrnombregrupo_len, 0x70, 10, 0
		
        jmp $


;================================
; RUTINAS UTILES PARA EL KERNEL
;================================
; LIMPIAR PANTALLA  
limpiar_pantalla:
		xor edi, edi
		mov ecx, 1000       ; 80*25/2 = 1000 (escribo de a dwords, es decir 2 caracteres)
		xor eax, eax        ; muevo el carater nulo 
    .limpiar:			
        stosd               ; [es:edi] <- eax; edi <- edi+4
        loop .limpiar
        ret

; IMPRIMIR LINEAS DE ARRIBA Y ABAJO
imprimir_lineas:
        xor edi, edi        ; base para fila de arriba
        mov esi, 0xF00      ; base para fila de abajo 3840 = 80x24x2
        mov ecx, 80         ; cant columnas(ver enunciado)
        xor ebx, ebx        ; indice
        mov ax, 0x7800      ; caracter a escribir
    .colocar_blancos:
        mov [es:edi + ebx], ax  ; lleno arriba arriba
        mov [es:esi + ebx], ax  ; lleno abajo abajo
        add ebx, 2              
        loop .colocar_blancos
    
        ret
        
;=======================================================================
; OJO a20.asm cambia a 16 bits - NO HAY QUE ESCRIBIR NADA DEBAJO DE ESTO
;=======================================================================
%include "a20.asm"
